手把手教你使用linux摄像头(V4L2框架) 您所在的位置:网站首页 IPC摄像头 用的什么系统 手把手教你使用linux摄像头(V4L2框架)

手把手教你使用linux摄像头(V4L2框架)

2024-01-01 23:48| 来源: 网络整理| 查看: 265

前言

本系统教程分为3篇,由浅至深地教你在Linux上应用摄像头,为以后在视觉等领域的应用打下基础: 1.本篇为基础学习篇,使用摄像头拍照获取.jpg格式图片 2.在ubuntu上获取动态读取摄像头的视频流并显示在pc上 3.在linux嵌入式开发板lcd上显示摄像头拍摄的视频

什么是V4L2框架

市场上出售着种类繁多的摄像头,他们的型号不同,厂商不同。这样子的话,每一次换一个摄像头难道就要我们自己去写一个驱动吗?这样子太麻烦了而且没有必要,于是就出现了v4l2框架,现在的摄像头都适配这个主流框架(就算不适配厂商也会想尽办法去适配以此来增加自己产品的畅销性)。这个v4l2适配了多种接口的摄像头。我们只需要学习一个简单的V4L2编程就可以通用所有摄像头了!我们知道linux的摄像头编程应用在人工智能嵌入式很热门,下面我来手把手教你linux是怎样驱动摄像头的。

驱动流程

本次教程在pc的虚拟机中实战,想要在嵌入式设备运行只要使用交叉编译器编译出可执行文件再运行即可。新手建议先再pc端使用usb摄像头实验,等学会了再调试到嵌入式设备中。

1.打开设备

当我们摄像头插入到电脑后,再/dev目录下会出现相应的摄像头video节点如图: 在这里插入图片描述 我们需要找到摄像头对应的节点,可以每个都试一试。

#include #include #include #include #include #include int main(void) { int fd = open("/dev/video0",O_RDWR); if (fd int fd = open("/dev/video1",O_RDWR); if (fd vfmt.index = i; i++; int ret = ioctl(fd,VIDIOC_ENUM_FMT,&vfmt); if (ret int fd = open("/dev/video0",O_RDWR);//根据自己的摄像头设备节点打开 if (fd perror("设置格式失败1"); } memset(&vfmt,0,sizeof(vfmt)); vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ret = ioctl(fd,VIDIOC_G_FMT,&vfmt); if (ret printf("设置成功!"); }else { printf("设置失败3"); } close(fd); return 0; }

打印出:设置成功 即可。 在这里插入图片描述

4.申请内核缓冲区队列

这里也是一样,直接告诉大家VIDIOC_REQBUFS操作命令是申请缓冲区队列。 在这里插入图片描述

#include #include #include #include #include #include #include #include #include int main(void) { int fd = open("/dev/video0",O_RDWR); if (fd perror("设置格式失败1"); } //申请内核空间 struct v4l2_requestbuffers reqbuffer; reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; reqbuffer.count = 4; //申请4个缓冲区 reqbuffer.memory = V4L2_MEMORY_MMAP; //映射方式 ret = ioctl(fd,VIDIOC_REQBUFS,&reqbuffer); if (ret int fd = open("/dev/video0",O_RDWR); if (fd perror("设置格式失败1"); } //申请内核空间 struct v4l2_requestbuffers reqbuffer; reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; reqbuffer.count = 4; //申请4个缓冲区 reqbuffer.memory = V4L2_MEMORY_MMAP; //映射方式 ret = ioctl(fd,VIDIOC_REQBUFS,&reqbuffer); if (ret //使用for对四个申请的空间进行轮询 mapbuffer.index = i; ret = ioctl(fd,VIDIOC_QUERYBUF,&mapbuffer); //从内核空间中查询一个空间作映射 if (ret perror("放回失败"); } } close(fd); return 0; } 6.采集帧数据

采集有四个命令: VIDIOC_STREAMON(开始采集写数据到队列中) VIDIOC_DQBUF(告诉内核我要某一个数据,内核不可以修改我正在采集的地方的数据) VIDIOC_QBUF(告诉内核我已经使用完毕,内核可以写入了) VIDIOC_STREAMOFF(停止采集-不在向队列中写数据)

#include #include #include #include #include #include #include #include #include #include int main(void) { int fd = open("/dev/video0",O_RDWR); if (fd perror("设置格式失败1"); } //申请内核空间 struct v4l2_requestbuffers reqbuffer; reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; reqbuffer.count = 4; //申请4个缓冲区 reqbuffer.memory = V4L2_MEMORY_MMAP; //映射方式 ret = ioctl(fd,VIDIOC_REQBUFS,&reqbuffer); if (ret mapbuffer.index = i; ret = ioctl(fd,VIDIOC_QUERYBUF,&mapbuffer); //从内核空间中查询一个空间作映射 if (ret perror("放回失败"); } } //开始采集 int type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ret = ioctl(fd,VIDIOC_STREAMON,&type); if (ret perror("读取数据失败"); } FILE *file=fopen("my.jpg", "w+"); //打开一个文件 fwrite( mptr[readbuffer.index],readbuffer.length,1,file);//写入文件 fclose(file); //写入完成,关闭文件 //通知内核使用完毕 ret = ioctl(fd, VIDIOC_QBUF, &readbuffer); if(ret


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有